package com.qing.demo.netty.demo1.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @author caozhipeng
 * @date 2025/7/22
 */
public abstract class ChannelAdapter extends Thread{

    private Selector selector;

    private ChannelHandler channelHandler;

    private Charset charset;

    public ChannelAdapter(Selector selector, Charset charset) {
        this.selector = selector;
        this.charset = charset;
    }

    @Override
    public void run() {
        try {
            while (true) {
                selector.select(1000);
                Set<SelectionKey> selectionKeys=selector.selectedKeys();
                Iterator<SelectionKey> iterator=selectionKeys.iterator();
                SelectionKey key=null;
                while (iterator.hasNext()){
                    key=iterator.next();
                    iterator.remove();
                    handleInput(key);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void handleInput(SelectionKey key) throws IOException {
        if(!key.isValid())return;
//       客户端 SocketChannel
        Class<?> superclass=key.channel().getClass().getSuperclass();
        if(superclass== SocketChannel.class){
            SocketChannel socketChannel=(SocketChannel) key.channel();
            if(key.isConnectable()){
                if(socketChannel.finishConnect()){
                    channelHandler=new ChannelHandler(socketChannel,charset);
                    channelActive(channelHandler);
                    socketChannel.register(selector,SelectionKey.OP_READ);
                }
            }
        }
//        服务端 ServerSocketChannel
        if(superclass== ServerSocketChannel.class){
            if(key.isAcceptable()){
                ServerSocketChannel serverSocketChannel=(ServerSocketChannel) key.channel();
                SocketChannel socketChannel=serverSocketChannel.accept();
                socketChannel.configureBlocking(false);
                socketChannel.register(selector,SelectionKey.OP_READ);

                channelHandler=new ChannelHandler(socketChannel,charset);
                channelActive(channelHandler);
            }
        }

        if(key.isReadable()){
            SocketChannel socketChannel= (SocketChannel) key.channel();
            ByteBuffer readBuffer=ByteBuffer.allocate(1024);
            int readBytes=socketChannel.read(readBuffer);
            if(readBytes>0){
                readBuffer.flip();
                byte[] bytes=new byte[readBuffer.remaining()];
                readBuffer.get(bytes);
                channelRead(channelHandler,new String(bytes,charset));
            }else if(readBytes<0){
                key.cancel();
                socketChannel.close();
            }
        }
    }

    public abstract void channelActive(ChannelHandler channelHandler) ;
    public abstract void channelRead(ChannelHandler channelHandler,Object msg) ;
}
